#include <functional>
#include <algorithm>

template<class T>
class auto_ptr
{
private:
   typedef auto_ptr<T> Self;
   typedef std::function<void(T*)> DelType;

public:
   auto_ptr(T* src = nullptr, DelType del = &auto_ptr::DefaultDel)
      :_src(src), _del(del)
   {}

   // 管理权转移
   auto_ptr(const Self& other)
      :_src(other._src), _del(other._del)
   {
      other._src = nullptr;
   }

   Self operator=(const Self& other)
   {
      if (this != &other)
      {
	 _src = other._src;
	 _del = other._del;
	 other._src = nullptr;
      }
      return *this;
   }

   ~auto_ptr()
   {
      _del(_src);
   }

private:
   static void DefaultDel(T* src)
   {
      delete src;
   }

private:
   T* _src;
   DelType _del; //定制删除器
};

template<class T>
class shared_ptr
{
private:
   typedef shared_ptr<T> Self;
   typedef std::function<void(T*)> DelType;

public:
   shared_ptr(T* src = nullptr, DelType del = &shared_ptr::DefaultDel)
      :_ref_cnt(nullptr), _src(src), _del(del)
   {
      _ref_cnt = new int(1);
   }

   shared_ptr(const Self& other)
      :_ref_cnt(other._ref_cnt),
      _src(other._src), _del(other._del)
   {
      ++(*_ref_cnt);
   }

   Self operator=(const Self& other)
   {
      if (this != &other)
      {
	 // 针对当前引用对象的处理
	 this->~shared_ptr();
	 // 针对新引用对象的处理
	 _src = other._src;
	 _ref_cnt = other._ref_cnt;
	 _del = other._del;
	 ++(*_ref_cnt);
      }
      return *this;
   }

   void swap(Self& other)
   {
      std::swap(_ref_cnt, other._ref_cnt);
      std::swap(_src, other._src);
      std::swap(_del, other._del);
   }

   ~shared_ptr()
   {
      if (--(*_ref_cnt) == 0) {
	 _del(_src);
	 delete _ref_cnt;
	 _src = nullptr;
	 _ref_cnt = nullptr;
      }
   }

private:
   static void DefaultDel(T* src)
   {
      delete src;
   }

private:
   int *_ref_cnt;
   T* _src;
   DelType _del;
};
